from complexityMeasure.CalcComplexity import CalcComplexity
from complexityMeasure.RandomSampling import RandomSampling
from complexityMeasure.VariatePaiPartition import VariatePaiPartition
from complexityMeasure.DescDataPartition import DescDataPartition
from complexityMeasure.RandomSampleBlocks import RandomSampleBlocks
from view.endSrc.tDataset import tDataset
from view.endSrc.MySqlConn import MySqlConn
from view.endSrc.DBConfig import DBConfig
import matplotlib.pyplot as plt
import numpy as np


class ComplexityExperiment:

    def __init__(self, nOb, name, observerGenClassName, clusterEstClassName, p2pClassName, n2nClassName,
                  maxob, minob, filterCfgJSONDict):
        self.nOb = nOb
        self.name = name
        self.observerGenClassName = observerGenClassName
        self.clusterEstClassName = clusterEstClassName
        self.p2pClassName = p2pClassName
        self.n2nClassName = n2nClassName
        self.maxob = maxob
        self.minob = minob
        self.filterCfgJSONDict = filterCfgJSONDict
        self.sqlconn = MySqlConn(DBConfig(name))

    def setConfig(self, nOb, name, observerGenClassName, clusterEstClassName, p2pClassName, n2nClassName,
                  maxob, minob, filterCfgJSONDict):
        self.nOb = nOb
        self.name = name
        self.observerGenClassName = observerGenClassName
        self.clusterEstClassName = clusterEstClassName
        self.p2pClassName = p2pClassName
        self.n2nClassName = n2nClassName
        self.maxob = maxob
        self.minob = minob
        self.filterCfgJSONDict = filterCfgJSONDict
        self.sqlconn = MySqlConn(DBConfig(name))

    def calcComplexity(self, ids):
        if isinstance(ids, int):
            ids = [ids]

        complexityLst = []
        for id in ids:
            ds = tDataset(self.sqlconn)
            ds.readDataset(id)
            cc = CalcComplexity(ds.nCols)
            cc.calcClusterNum(self.sqlconn, self.name, id, self.observerGenClassName, self.nOb, self.clusterEstClassName,
                              self.p2pClassName, self.n2nClassName, self.filterCfgJSONDict, self.maxob, self.minob)
            cc.calcEntropy()
            complexity = cc.calc()
            complexityLst.append(complexity)

        return complexityLst

    @staticmethod
    def compare_plot(total, rspc, blockc):
        size1 = len(rspc)
        size2 = len(blockc)
        size = size1 + size2
        plt.plot([0, size-1], [total, total])
        plt.scatter(list(range(size1)), rspc, c='b')
        plt.scatter(list(range(size1, size)), blockc, c='r')
        plt.show()


if __name__ == '__main__':
    # EXPERIMENT 1-------------------------------------------------------------------------
    # nOb = 5
    # name = 'complexity'
    # observerGenClassName = 'EdgeObserverGenerator'
    # clusterEstClassName = 'GaussianClustersEstimatorBy1D'
    # p2pClassName = 'One2OneDistance'
    # n2nClassName = 'N2NDistances'
    # maxob = 7
    # minob = 1
    # filterCfgJSONDict = {'KdeFilter': {'topPer': 0.05}, 'DensityPeakFilter': {'cutoffPer': 0.1}}
    # cexp = ComplexityExperiment(nOb=nOb, name=name, observerGenClassName=observerGenClassName,
    #                             clusterEstClassName=clusterEstClassName, p2pClassName=p2pClassName,
    #                             n2nClassName=n2nClassName, maxob=maxob, minob=minob,
    #                             filterCfgJSONDict=filterCfgJSONDict)
    # dsId = 244
    # ds = tDataset(cexp.sqlconn)
    # ds.readDataset(dsId)
    # rsp_ids = None
    # block_ids = None
    # # rsp
    # rs = RandomSampling(ds.m_dataset, ds.m_labels)
    # if rsp_ids is None:
    #     rs.randomPartition(10)
    #     rsp_ids = rs.saveToDB(des='', fileName='rsp', name='rsp')
    # print('rsp_ids', rsp_ids)
    # if block_ids is None:
    #     rs.simplePartition(10, isEven=True)
    #     block_ids = rs.saveToDB(des='', fileName='simple_block', name='simple_block')
    # print('block_ids', block_ids)
    #
    # # Complexity
    # overall_complexity = cexp.calcComplexity(dsId)[0]
    # print('overall_complexity', overall_complexity)
    # rsp_complexityLst = cexp.calcComplexity(rsp_ids)
    # print('rsp_complexityLst', rsp_complexityLst)
    # block_complexityLst = cexp.calcComplexity(block_ids)
    # print('block_complexityLst', block_complexityLst)
    #
    # print('')
    # print('overall_complexity', overall_complexity)
    # print('rsp_complexityLst', rsp_complexityLst)
    # print('block_complexityLst', block_complexityLst)
    # cexp.compare_plot(overall_complexity, rsp_complexityLst, block_complexityLst)

    # EXPERIMENT 2-------------------------------------------------------------------------
    # nOb = 5
    # name = 'complexity'
    # observerGenClassName = 'EdgeObserverGenerator'
    # clusterEstClassName = 'GaussianClustersEstimatorBy1D'
    # p2pClassName = 'One2OneDistance'
    # n2nClassName = 'N2NDistances'
    # maxob = 7
    # minob = 1
    # filterCfgJSONDict = {'KdeFilter': {'topPer': 0.1}, 'DensityPeakFilter': {'cutoffPer': 0.1}}
    # cexp = ComplexityExperiment(nOb=nOb, name=name, observerGenClassName=observerGenClassName,
    #                             clusterEstClassName=clusterEstClassName, p2pClassName=p2pClassName,
    #                             n2nClassName=n2nClassName, maxob=maxob, minob=minob, filterCfgJSONDict=filterCfgJSONDict)
    #
    # dsId = 244
    # ds = tDataset(cexp.sqlconn)
    # ds.readDataset(dsId)
    # sizeLst = [50000, 40000, 30000, 20000, 10000, 8000, 5000, 3000, 1000, 900, 800, 700, 600, 500, 400, 300]
    # ids = [436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451]
    # dp = DescDataPartition(ds.m_dataset, ds.m_labels)
    # if ids is None:
    #     dp.DescPartition(sizeLst)
    #     ids = dp.saveToDB(des='', fileName='Desc', name='Desc')
    # print('Desc_ids', ids)
    #
    # # Complexity
    # desc_complexity = cexp.calcComplexity(ids)
    # print('desc_complexity', desc_complexity)
    #
    # plt.plot(sizeLst, desc_complexity, marker='o')
    # plt.gca().invert_xaxis()
    # plt.show()

    # EXPERIMENT 3.1-------------------------------------------------------------------------
    # nOb = 5
    # name = 'complexity'
    # observerGenClassName = 'EdgeObserverGenerator'
    # clusterEstClassName = 'GaussianClustersEstimatorBy1D'
    # p2pClassName = 'One2OneDistance'
    # n2nClassName = 'N2NDistances'
    # maxob = 4
    # minob = 1
    # filterCfgJSONDict = {'KdeFilter': {'topPer': 0.1}, 'DensityPeakFilter': {'cutoffPer': 0.1}}
    # cexp = ComplexityExperiment(nOb=nOb, name=name, observerGenClassName=observerGenClassName,
    #                             clusterEstClassName=clusterEstClassName, p2pClassName=p2pClassName,
    #                             n2nClassName=n2nClassName, maxob=maxob, minob=minob,
    #                             filterCfgJSONDict=filterCfgJSONDict)
    #
    # dsId = 452
    # ds = tDataset(cexp.sqlconn)
    # ds.readDataset(dsId)
    # num = 10
    # ids = [463, 464, 465, 466, 467, 468, 469, 470, 471, 472]
    # vp = VariatePaiPartition(ds.m_dataset, ds.m_labels)
    # if ids is None:
    #     vp.partition(10)
    #     ids = vp.saveToDB(des='', fileName='variaE', name='variaE')
    # print('VariaE_ids', ids)
    #
    # # Complexity
    # variaE_complexity = cexp.calcComplexity(ids)
    # print('variaE_complexity', variaE_complexity)
    #
    # plt.plot(np.linspace(0, 1, num), variaE_complexity, marker='o')
    # plt.show()

    # EXPERIMENT 3.2-------------------------------------------------------------------------
    # nOb = 5
    # name = 'complexity'
    # observerGenClassName = 'EdgeObserverGenerator'
    # clusterEstClassName = 'GaussianClustersEstimatorBy1D'
    # p2pClassName = 'One2OneDistance'
    # n2nClassName = 'N2NDistances'
    # maxob = 11
    # minob = 2
    # filterCfgJSONDict = {'KdeFilter': {'topPer': 1}, 'DensityPeakFilter': {'cutoffPer': 0.1}}
    # cexp = ComplexityExperiment(nOb=nOb, name=name, observerGenClassName=observerGenClassName,
    #                             clusterEstClassName=clusterEstClassName, p2pClassName=p2pClassName,
    #                             n2nClassName=n2nClassName, maxob=maxob, minob=minob,
    #                             filterCfgJSONDict=filterCfgJSONDict)
    #
    # num = 10
    # ids = [774, 773, 772, 771, 770, 769, 768, 767, 766]
    # kLst = [10, 9, 8, 7, 6, 5, 4, 3, 2]
    # # Complexity
    # variaK_complexity = cexp.calcComplexity(ids)
    # print('variaK_complexity', variaK_complexity)
    #
    # plt.plot(kLst, variaK_complexity, marker='o')
    # plt.show()

    # pp = [
    #     [0.4964964964964965, 0.5035035035035035],
    #     [0.001001001001001001, 0.4394394394394394, 0.5595595595595596],
    #     [0.001001001001001001, 0.001001001001001001, 0.4144144144144144, 0.5835835835835835],
    #     [0.001001001001001001, 0.001001001001001001, 0.005005005005005005, 0.35235235235235235, 0.6406406406406406],
    #     [0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.005005005005005005, 0.34034034034034033, 0.6516516516516516],
    #     [0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.36436436436436437, 0.6306306306306306],
    #     [0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.35135135135135137, 0.6426426426426426],
    #     [0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.012012012012012012, 0.2732732732732733, 0.7087087087087087],
    #     [0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.001001001001001001, 0.03303303303303303, 0.2012012012012012, 0.7587587587587588]
    # ]
    #
    # lst = []
    # for paiList in pp:
    #     cc = CalcComplexity(2)
    #     cc.K = len(paiList)
    #     cc.paiList = paiList
    #     cc.calcEntropy()
    #     complexity = cc.calc()
    #     lst.append(complexity)
    #
    # kLst = [2, 3, 4, 5, 6, 7, 8, 9, 10]
    # plt.plot(kLst, lst, marker='o')
    # plt.show()

    # EXPERIMENT 4-------------------------------------------------------------------------
    # nOb = 5
    # name = 'complexity'
    # observerGenClassName = 'EdgeObserverGenerator'
    # clusterEstClassName = 'GaussianClustersEstimatorBy1D'
    # p2pClassName = 'One2OneDistance'
    # n2nClassName = 'N2NDistances'
    # maxob = None
    # minob = None
    # filterCfgJSONDict = {'KdeFilter': {'topPer': 0.5}, 'DensityPeakFilter': {'cutoffPer': 0.1}}
    # cexp = ComplexityExperiment(nOb=nOb, name=name, observerGenClassName=observerGenClassName,
    #                             clusterEstClassName=clusterEstClassName, p2pClassName=p2pClassName,
    #                             n2nClassName=n2nClassName, maxob=maxob, minob=minob, filterCfgJSONDict=filterCfgJSONDict)
    #
    # dsId = 641
    # hdfsnum = 10
    # ds = tDataset(cexp.sqlconn)
    # ds.readDataset(dsId)
    # rows = ds.nRows
    # rspnumLst = [125, 100, 80, 50, 40, 32, 25, 20, 16, 10, 8, 5, 4, 2, 1]
    # rspblocksizeLst = [rows/i for i in rspnumLst]
    # rsp_ids = [[642, 643, 644, 645, 646, 647, 648, 649, 650, 651], [652, 653, 654, 655, 656, 657, 658, 659, 660, 661], [662, 663, 664, 665, 666, 667, 668, 669, 670, 671], [672, 673, 674, 675, 676, 677, 678, 679, 680, 681], [682, 683, 684, 685, 686, 687, 688, 689, 690, 691], [692, 693, 694, 695, 696, 697, 698, 699, 700, 701], [702, 703, 704, 705, 706, 707, 708, 709, 710, 711], [712, 713, 714, 715, 716, 717, 718, 719, 720, 721], [722, 723, 724, 725, 726, 727, 728, 729, 730, 731], [732, 733, 734, 735, 736, 737, 738, 739, 740, 741], [742, 743, 744, 745, 746, 747, 748, 749], [750, 751, 752, 753, 754], [755, 756, 757, 758], [759, 760], [761]]
    #
    # dp = RandomSampleBlocks(ds.m_dataset, ds.m_labels)
    # if rsp_ids is None:
    #     rsp_ids = []
    #     for rspnum in rspnumLst:
    #         dp.partition(hdfsnum, rspnum)
    #         ids = dp.saveToDB(des='', fileName='Desc', name='Desc', limit=10)
    #         rsp_ids.append(ids)
    # print('rsp_ids', rsp_ids)
    #
    # # Complexity
    # complexity = []
    # for ids in rsp_ids:
    #     cLst = cexp.calcComplexity(ids)
    #     complexity.append(np.mean(cLst))
    # print('complexity', complexity)
    #
    # plt.plot(rspblocksizeLst, complexity, marker='o')
    # plt.show()

    # sample size-------------------------------------------------------------------------

    # nOb = 6
    # name = 'sample_size'
    # observerGenClassName = 'EdgeObserverGenerator'
    # clusterEstClassName = 'GaussianClustersEstimatorBy1D'
    # p2pClassName = 'One2OneDistance'
    # n2nClassName = 'N2NDistances'
    # maxob = None
    # minob = None
    # filterCfgJSONDict = {'KdeFilter': {'topPer': 0.5}, 'DensityPeakFilter': {'cutoffPer': 0.1}}
    # cexp = ComplexityExperiment(nOb=nOb, name=name, observerGenClassName=observerGenClassName,
    #                             clusterEstClassName=clusterEstClassName, p2pClassName=p2pClassName,
    #                             n2nClassName=n2nClassName, maxob=maxob, minob=minob, filterCfgJSONDict=filterCfgJSONDict)
    #
    # dsId = 795
    # hdfsnum = 10
    # ds = tDataset(cexp.sqlconn)
    # ds.readDataset(dsId)
    # rows = ds.nRows
    # rspnumLst = [125, 100, 80, 50, 40, 32, 25, 20, 16, 10, 8, 5, 4, 2, 1]
    # rspblocksizeLst = [rows/i for i in rspnumLst]
    # rsp_ids = [[826, 827, 828, 829, 830, 831, 832, 833, 834, 835], [836, 837, 838, 839, 840, 841, 842, 843, 844, 845],
    #            [846, 847, 848, 849, 850, 851, 852, 853, 854, 855], [856, 857, 858, 859, 860, 861, 862, 863, 864, 865],
    #            [866, 867, 868, 869, 870, 871, 872, 873, 874, 875], [876, 877, 878, 879, 880, 881, 882, 883, 884, 885],
    #            [886, 887, 888, 889, 890, 891, 892, 893, 894, 895], [896, 897, 898, 899, 900, 901, 902, 903, 904, 905],
    #            [906, 907, 908, 909, 910, 911, 912, 913, 914, 915], [916, 917, 918, 919, 920, 921, 922, 923, 924, 925],
    #            [926, 927, 928, 929, 930, 931, 932, 933], [934, 935, 936, 937, 938], [939, 940, 941, 942], [943, 944],
    #            [945]]
    #
    # dp = RandomSampleBlocks(ds.m_dataset, ds.m_labels)
    # if rsp_ids is None:
    #     rsp_ids = []
    #     for rspnum in rspnumLst:
    #         dp.partition(hdfsnum, rspnum)
    #         ids = dp.saveToDB(des='', fileName='Desc', name='Desc', limit=10)
    #         rsp_ids.append(ids)
    # print('rsp_ids', rsp_ids)
    #
    # # Complexity
    # complexity = []
    # for ids in rsp_ids:
    #     cLst = cexp.calcComplexity(ids)
    #     complexity.append(np.mean(cLst))
    # print('complexity', complexity)
    #
    # plt.plot(rspblocksizeLst, complexity, marker='o')
    # plt.show()

    # nOb = 6
    # name = 'complexity'
    # observerGenClassName = 'EdgeObserverGenerator'
    # clusterEstClassName = 'GaussianClustersEstimatorBy1D'
    # p2pClassName = 'One2OneDistance'
    # n2nClassName = 'N2NDistances'
    # maxob = None
    # minob = None
    # filterCfgJSONDict = {'KdeFilter': {'topPer': 1}, 'DensityPeakFilter': {'cutoffPer': 0.05}}
    # cexp = ComplexityExperiment(nOb=nOb, name=name, observerGenClassName=observerGenClassName,
    #                             clusterEstClassName=clusterEstClassName, p2pClassName=p2pClassName,
    #                             n2nClassName=n2nClassName, maxob=maxob, minob=minob,
    #                             filterCfgJSONDict=filterCfgJSONDict)
    #
    # dsId = 1208
    # hdfsnum = 10
    # ds = tDataset(cexp.sqlconn)
    # ds.readDataset(dsId)
    # rows = ds.nRows
    # rspnumLst = [125, 100, 60, 50, 40, 24, 20, 12, 10, 8, 5, 4, 2, 1]
    # rspblocksizeLst = [rows / i for i in rspnumLst]
    # rsp_ids = [[1209, 1210, 1211, 1212, 1213], [1214, 1215, 1216, 1217, 1218], [1219, 1220, 1221, 1222, 1223],
    #            [1224, 1225, 1226, 1227, 1228], [1229, 1230, 1231, 1232, 1233], [1234, 1235, 1236, 1237, 1238],
    #            [1239, 1240, 1241, 1242, 1243], [1244, 1245, 1246, 1247, 1248], [1249, 1250, 1251, 1252, 1253],
    #            [1254, 1255, 1256, 1257, 1258], [1259, 1260, 1261, 1262, 1263], [1264, 1265, 1266, 1267], [1268, 1269],
    #            [1270]]
    #
    #
    # dp = RandomSampleBlocks(ds.m_dataset, ds.m_labels)
    # if rsp_ids is None:
    #     rsp_ids = []
    #     for rspnum in rspnumLst:
    #         dp.partition(hdfsnum, rspnum)
    #         ids = dp.saveToDB(des='', fileName='Desc', name='Desc', limit=5)
    #         rsp_ids.append(ids)
    # print('rsp_ids', rsp_ids)
    #
    # # Complexity
    # complexity = []
    # for ids in rsp_ids:
    #     cLst = cexp.calcComplexity(ids)
    #     complexity.append(np.mean(cLst))
    #     print('mid', complexity)
    # print('complexity', complexity)
    #
    # plt.plot(rspblocksizeLst, complexity, marker='o')
    # print('rspblocksizeLst', rspblocksizeLst)
    # plt.show()

    # check sample size-------------------------------------------------------------------------

    nOb = 6
    name = 'check_sample_size'
    observerGenClassName = 'EdgeObserverGenerator'
    clusterEstClassName = 'GaussianClustersEstimatorBy1D'
    p2pClassName = 'One2OneDistance'
    n2nClassName = 'N2NDistances'
    maxob = 3
    minob = 2
    filterCfgJSONDict = {'KdeFilter': {'topPer': 0.3}, 'DensityPeakFilter': {'cutoffPer': 0.1}}
    cexp = ComplexityExperiment(nOb=nOb, name=name, observerGenClassName=observerGenClassName,
                                clusterEstClassName=clusterEstClassName, p2pClassName=p2pClassName,
                                n2nClassName=n2nClassName, maxob=maxob, minob=minob, filterCfgJSONDict=filterCfgJSONDict)

    dsId = 1908
    hdfsnum = 10
    ds = tDataset(cexp.sqlconn)
    ds.readDataset(dsId)
    rows = ds.nRows
    rspnumLst = [125, 100, 80, 50, 40, 32, 25, 20, 16, 10, 8, 5, 4, 2]
    rspblocksizeLst = [rows/i for i in rspnumLst]
    rsp_ids = [[1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918],
               [1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928],
               [1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938],
               [1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948],
               [1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958],
               [1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968],
               [1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978],
               [1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988],
               [1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998],
               [1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008],
               [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016], [2017, 2018, 2019, 2020, 2021],
               [2022, 2023, 2024, 2025], [2026, 2027]]

    dp = RandomSampleBlocks(ds.m_dataset, ds.m_labels)
    if rsp_ids is None:
        rsp_ids = []
        for rspnum in rspnumLst:
            dp.partition(hdfsnum, rspnum)
            ids = dp.saveToDB(des='', fileName='Desc', name='Desc', limit=10)
            rsp_ids.append(ids)
    print('rsp_ids', rsp_ids)

    # Complexity
    complexity = []
    for ids in rsp_ids:
        cLst = cexp.calcComplexity(ids)
        complexity.append(np.mean(cLst))
        print('mid', complexity)
    print('complexity', complexity)

    plt.plot(rspblocksizeLst, complexity, marker='o')
    print('rspblocksizeLst', rspblocksizeLst)
    plt.show()
